
const anchor = require("@coral-xyz/anchor");
const {    ComputeBudgetProgram, PublicKey} = require("@solana/web3.js");
const getKeypair  = require('./wallet');
const config = require('./config');
class Program {
    constructor(nodeUrl){
        this.nodeUrl = nodeUrl;
        this.keypair = getKeypair();
        this.wallet = new anchor.Wallet(this.keypair);
        this.connection = new anchor.web3.Connection(nodeUrl);

        this.provider = new anchor.AnchorProvider(this.connection,this.wallet, 'recent');
        this.program = new anchor.Program(config.idl, this.provider);

    }
    async decode_and_verify (encoded_info, signatures){

        let instruction = await this.program.methods.decodeAndVerify(encoded_info, signatures).accounts({}).instruction();

        let instructions = [
            instruction
        ];
        let tx = new anchor.web3.Transaction();
        tx.add(...instructions);

        let txHash = null;
        try{
            txHash =await  this.connection.sendTransaction(tx, [this.keypair]);
            console.log('txHash: ',txHash);
        }catch (error) {
            console.log('error: ',error);
        }
    }
    async initialize() {
        let instruction = await this.program.methods.initialize().accounts({}).instruction();
        let instructions = [
            instruction
        ];
        let tx = new anchor.web3.Transaction();
        tx.add(...instructions);

        let txHash = null;
        try{
            txHash = await this.connection.sendTransaction(tx, [this.keypair]);
            console.log('txHash: ',txHash);
        }catch (error) {
            console.log('error: ',error);
        }
    }

    async outbound_call(network_id,contract_address, functionCallData,source_contract_address) {
        let instruction = await this.program.methods.outboundCall(network_id, contract_address, functionCallData,source_contract_address).accounts({}).instruction();
        let instructions = [
            instruction
        ];
        let tx = new anchor.web3.Transaction();
        tx.add(...instructions);

        let txHash = null;
        try{
            txHash = await this.connection.sendTransaction(tx, [this.keypair]);
            console.log('txHash: ',txHash);
        }catch (error) {
            console.log('error: ',error);
        }

    }
    async inbound_call(networkId,encodeInfo,encodedProof) {

        let instruction1 = ComputeBudgetProgram.setComputeUnitLimit({units:500000});
        let instruction2 = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100 });

        let instruction = await this.program.methods.inboundCall(networkId,encodeInfo,encodedProof).accounts({
            appProgram:new PublicKey(config.cpiAppProgramId),
        }).instruction();
        let instructions = [
            instruction1,
            instruction2,
            instruction
        ];
        let tx = new anchor.web3.Transaction();
        tx.add(...instructions);

        let txHash = null;
        try{
            txHash = await this.connection.sendTransaction(tx, [this.keypair]);
            console.log('txHash: ',txHash);
        }catch (error) {
            console.log('error: ',error);
        }
    }
    async cpi_rmv_receive() {
                let instruction1 = ComputeBudgetProgram.setComputeUnitLimit({units:500000});
        let instruction2 = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100 });

        let appPk = new PublicKey("CZqEB5Hu2gBx2ieBZHL3fWtde9R3dHSvjdsNgWYydzVK")

        let instruction = await this.program.methods.cpiRmvReceive().accounts({appinterface_program:appPk}).instruction();
        let instructions = [
            instruction1,
            instruction2,
            instruction
        ];
        let tx = new anchor.web3.Transaction();
        tx.add(...instructions);

        let txHash = null;
        try{
            txHash = await this.connection.sendTransaction(tx, [this.keypair]);
            console.log('txHash: ',txHash);
        }catch (error) {
            console.log('error: ',error);
        }
    }
}

module.exports = Program;